package com.qh.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;

/**
 * 
 * <p>提供通过Http协议上传的各种接口。如上传字符串、上传文件+参数等</p>
 * @version 1.0
 * @create 2011-7-1
 */
public class HttpUpload {
	/**
    * 
    * <p>上传字符串到服务器</p>
    * @param urlStr 上传的服务器接口地址
    * @param data 上传的字符串
    * @param encode 返回数据的编码格式
    * @return 服务器返回的字符串内容 
    */
	public static String upload(String urlStr, String data,String encode) throws Exception {
		URL url = new URL(urlStr);
		HttpURLConnection connection = (HttpURLConnection) url.openConnection();
		setConnectParam(connection, String.valueOf(data.length()));
		return upload(connection, data.getBytes(), encode);
	}

	/**
    * 
    * <p>上传二进制数据，主要用在需要上传图片等大数据量二进制文件的场合</p>
    * @param urlStr 上传的服务器接口地址
    * @param data 上传的数据buffer
    * @param encode 返回数据的编码格式
    * @return 服务器返回的字符串内容
    */
	public static String upload(String urlStr, byte[] data, String encode) throws Exception {
		URL url = new URL(urlStr);
		HttpURLConnection connection = (HttpURLConnection) url.openConnection();
		setConnectParam(connection, String.valueOf(data.length));
		return upload(connection, data, encode);
	}
	
	/**
    * 
    * <p>上传多个参数值，参数使用字符串对，以key=value&key=value的形式封装到http数据流中</p>
    * @param urlStr 上传的服务器接口地址
    * @param params 包含参数对的HashMap对象
    * @return 服务器返回的字符串内容
    */
	public static String upload(String urlStr, HashMap<String, String>params) throws Exception {
        PostMethod postMethod = new PostMethod(urlStr);
        Iterator<Entry<String, String>> iter = params.entrySet().iterator(); 
        while (iter.hasNext()) { 
            Entry<String, String> entry = (Entry<String, String>)iter.next(); 
            String key = entry.getKey(); 
            String val = entry.getValue(); 
            postMethod.addParameter(key,val);
           
        } 
        return post(postMethod);
    }
	
	/**
    * 
    * <p>上传一个文件，同时上传多个参数值，参数以multipart的形式封装到http数据流中</p>
    * @param urlStr 上传的服务器接口地址
    * @param fileName 上传的文件名称（包含全路径）
    * @param params 包含参数对的HashMap对象
    * @return 服务器返回的字符串内容
    */
	public static String uploadFile(String urlStr, String fileName, HashMap<String, String>params) throws Exception
    {
		try {
			MultipartEntity multipartContent = new MultipartEntity();
			FileBody fb = new FileBody(new File(fileName));
			StringBody fileCount;
			fileCount = new StringBody("1");
			multipartContent.addPart("file_count", fileCount);
			multipartContent.addPart("file", fb);
			return uploadMultipartData(urlStr, multipartContent, params);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			throw e;
		}
    }
	
	/**
    * 
    * <p>上传多个文件，同时上传多个参数值，参数以multipart的形式封装到http数据流中</p>
    * @param urlStr 上传的服务器接口地址
    * @param fileList 上传文件的名称列表（包含全路径）
    * @param params 包含参数对的HashMap对象
    * @return 服务器返回的字符串内容
    */
	public static String uploadFile(String urlStr, List<String>fileList, HashMap<String, String>params) throws Exception
	{
		try {
			MultipartEntity multipartContent = new MultipartEntity();
			
			StringBody fileCount = new StringBody(String.valueOf(fileList.size()));
			multipartContent.addPart("file_count", fileCount);
			
			for(int i=0; i<fileList.size(); i++) {
				String fileName = fileList.get(i);  
				FileBody fb = new FileBody(new File(fileName));
				multipartContent.addPart("file" + i + "_data", fb);
			}  
			return uploadMultipartData(urlStr, multipartContent, params);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			throw e;
		}
	}
	/**
	    * 
	    * 设置服务器连接参数
	    */
	private static void setConnectParam(HttpURLConnection connection, String length) {
		connection.setRequestProperty("Connection", "Keep-Alive");
		connection.setRequestProperty("Cache-Control", "no-cache");
		connection.setRequestProperty("Accept", "*/*");
		connection.setRequestProperty("Content-Type", "text/html");
		connection.setRequestProperty("User-Agent",
				"Mozilla/4.0 (compatible; MSIE 6.0; Windows 2000)");
		connection.setRequestProperty("Accept-Language", "zh-cn");
		connection.setRequestProperty("Accept-Encoding", "gzip, deflate");
		connection.setRequestProperty("Content-Length", length);
		connection.setConnectTimeout(30000);
		connection.setDoOutput(true);
	}
	/**
	    * 
	    * <p>上传多个文件</p>
	    * @param urlStr 上传的服务器地址
	    * @param params 包含参数对的byte
	    * @return 服务器返回的字符串内容
	    */
	private static String upload(HttpURLConnection connection, byte[] data, String encode) throws Exception {
		InputStream in=null;
		java.io.BufferedReader breader=null;
		try {
			connection.connect();
			connection.getOutputStream().write(data);
			if (connection.getResponseCode() == 200) {
				in = connection.getInputStream();
				breader = new BufferedReader(new InputStreamReader(in, encode));
				String str = breader.readLine();
				StringBuffer sb = new StringBuffer();
				while (str != null) {
					sb.append(str);
					str = breader.readLine();
				}
				return sb.toString();
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		} finally {
			if(null!=breader)
			{
				breader.close();
			}
			if(null!=in)
			{
				in.close();
			}
		}
		return "";
	}
	/**
	    * 上传多个数据
	    * 
	    * 
	    */
	private static String uploadMultipartData(String urlStr, MultipartEntity multipartContent, HashMap<String, String>params) throws Exception
	{
		try {
            HttpPost postRequest = new HttpPost(urlStr);
            
            Iterator<Entry<String, String>> iter = params.entrySet().iterator(); 
            while (iter.hasNext()) { 
            	Entry<String, String> entry = (Entry<String, String>)iter.next(); 
            	StringBody sb = new StringBody(entry.getValue());
            	String key = entry.getKey(); 
                multipartContent.addPart(key, sb);
            } 
            
            postRequest.setEntity(multipartContent);
            return post(postRequest);
		}
        catch (Exception e){
        	e.printStackTrace();
        	throw e;
        }
	}
		
	private static String post(HttpPost postRequest) throws Exception
	{
		org.apache.http.client.HttpClient httpClient = new DefaultHttpClient();
        HttpResponse res;
		try {
			res = httpClient.execute(postRequest);
		} catch (ClientProtocolException e) {
			e.printStackTrace();
			throw e;
		} catch (IOException e) {
			e.printStackTrace();
			throw e;
		}
			
        if (res != null && res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
        	InputStream instream = res.getEntity().getContent();
            try {
                BufferedReader reader = new BufferedReader(
                        new InputStreamReader(instream));
                return reader.toString();

            } catch (RuntimeException ex) {

            	postRequest.abort();
                throw ex;

            } finally {
                instream.close();
            }
        }
        
        httpClient.getConnectionManager().shutdown();
        return "no";
	}
	
	private static String post(HttpMethod postMethod) throws Exception
	{
		
		postMethod.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET,"utf-8");
		HttpClient httpClient = new HttpClient();
		try {
			 HttpConnectionManagerParams managerParams = httpClient.getHttpConnectionManager().getParams(); 
			 managerParams.setConnectionTimeout(30000);
			 managerParams.setSoTimeout(3000);
			
	
	       // 使用系统提供的默认的恢复策略
	       postMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,new DefaultHttpMethodRetryHandler());
	  
	       int statusCode = httpClient.executeMethod(postMethod);
			
			if (statusCode != HttpStatus.SC_OK) {
				System.err.println("Method failed: " + postMethod.getStatusLine());
		    }
		    // 读取内容

		    return new String(postMethod.getResponseBody());
		} catch  (org.apache.commons.httpclient.HttpException e) {
			// 发生致命的异常，可能是协议不对或者返回的内容有问题 
	
			e.printStackTrace();
		}
		catch(SocketTimeoutException e)
		{
			 return "timeout";
		}
		catch  (IOException e) {
			// 发生网络异常 
			e.printStackTrace();
			
			 return "timeout";
		}
		finally {
			// 释放连接 
			postMethod.releaseConnection();
		}
        return "no";
	}
	
}
